﻿using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using GalaSoft.MvvmLight.Threading;
using HIWSystem.Common;
using HIWSystem.Helpers;
using HIWSystem.Models;
using LabelManager2;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;

namespace HIWSystem.ViewModel
{
    public class LabelPrintViewModel : ViewModelBase
    {
        public LabelPrintViewModel()
        {
            DispatcherHelper.Initialize();
            //消息标志token：ViewAlert，用于标识只阅读某个或者某些Sender发送的消息，并执行相应的处理，所以Sender那边的token要保持一致
            //执行方法Action：ShowReceiveInfo，用来执行接收到消息后的后续工作，注意这边是支持泛型能力的，所以传递参数很方便。
            Messenger.Default.Register<string>(this, "LstPreprintSnClickCmd", LstPreprintSnCheckBoxClickHandler);
            Messenger.Default.Register<string>(this, "InputBox", ReceiveReprintCount);
        }

        #region 属性

        //用于判断是不是第一次触发过滤，是则备份原始数据源
        private bool isFirstFilterPN = true;

        private bool isFirstFilterWO = true;

        //用于再ComboBox控件中输入内容过滤时备份原始的数据源
        //当没有输入内容时恢复到备份的原始数据源
        private ObservableCollection<PartNumberEntity> backupPNs = null;

        private ObservableCollection<WOEntity> backupWOs = null;

        private ObservableCollection<PartNumberEntity> pns;

        /// <summary>
        /// 机种实体集合
        /// </summary>
        public ObservableCollection<PartNumberEntity> PNs
        {
            get { return pns; }
            set { pns = value; this.RaisePropertyChanged(() => PNs); }
        }

        private PartNumberEntity selectedPartNumber;

        /// <summary>
        /// 选择的机种实体
        /// </summary>
        public PartNumberEntity SelectedPartNumber
        {
            get { return selectedPartNumber; }
            set { selectedPartNumber = value; this.RaisePropertyChanged(() => SelectedPartNumber); }
        }

        private string pn;

        /// <summary>
        /// 机种
        /// </summary>
        public string PN
        {
            get { return pn; }
            set { pn = value; this.RaisePropertyChanged(() => PN); }
        }

        private bool isOpenComboPNDropDown;

        /// <summary>
        /// 是否打开机种下拉框选项卡
        /// </summary>
        public bool IsOpenComboPNDropDown
        {
            get { return isOpenComboPNDropDown; }
            set { isOpenComboPNDropDown = value; this.RaisePropertyChanged(() => IsOpenComboPNDropDown); }
        }

        private string searchPNText;

        /// <summary>
        /// 机种下拉框中输入的文本内容
        /// </summary>
        public string SearchPNText
        {
            get { return searchPNText; }
            set { searchPNText = value; this.RaisePropertyChanged(() => SearchPNText); }
        }

        private ObservableCollection<WOEntity> wos;

        /// <summary>
        /// 工单实体集合
        /// </summary>
        public ObservableCollection<WOEntity> WOs
        {
            get { return wos; }
            set { wos = value; this.RaisePropertyChanged(() => WOs); }
        }

        private WOEntity selectedWO;

        /// <summary>
        /// 选择的工单实体
        /// </summary>
        public WOEntity SelectedWO
        {
            get { return selectedWO; }
            set { selectedWO = value; this.RaisePropertyChanged(() => SelectedWO); }
        }

        private string wo;

        /// <summary>
        /// 选择的工单
        /// </summary>
        public string WO
        {
            get { return wo; }
            set { wo = value; this.RaisePropertyChanged(() => WO); }
        }

        private bool isOpenComboWODropDown;

        /// <summary>
        /// 是否打开工单下拉框选项卡
        /// </summary>
        public bool IsOpenComboWODropDown
        {
            get { return isOpenComboWODropDown; }
            set { isOpenComboWODropDown = value; this.RaisePropertyChanged(() => IsOpenComboWODropDown); }
        }

        private string searchWOText;

        /// <summary>
        /// 工单下拉列表框中输入的文本
        /// </summary>
        public string SearchWOText
        {
            get { return searchWOText; }
            set { searchWOText = value; this.RaisePropertyChanged(() => SearchWOText); }
        }

        private ObservableCollection<SNEntity> preprintSns;

        /// <summary>
        /// 预打印的序列号集合
        /// </summary>
        public ObservableCollection<SNEntity> PreprintSns
        {
            get { return preprintSns; }
            set { preprintSns = value; this.RaisePropertyChanged(() => PreprintSns); }
        }

        private ObservableCollection<SNEntity> printedSns;

        /// <summary>
        /// 已打印的序列号集合
        /// </summary>
        public ObservableCollection<SNEntity> PrintedSns
        {
            get { return printedSns; }
            set { printedSns = value; this.RaisePropertyChanged(() => PrintedSns); }
        }

        //ReprintSns
        private ObservableCollection<SNEntity> reprintSns;

        /// <summary>
        /// 补打的序列号集合
        /// </summary>
        public ObservableCollection<SNEntity> ReprintSns
        {
            get { return reprintSns; }
            set { reprintSns = value; this.RaisePropertyChanged(() => ReprintSns); }
        }

        private int noPrintCount;

        /// <summary>
        /// 预打印的总数量
        /// </summary>
        public int NoPrintCount
        {
            get { return noPrintCount; }
            set { noPrintCount = value; this.RaisePropertyChanged(() => NoPrintCount); }
        }

        private int checkCount;

        /// <summary>
        /// 选择的数量
        /// </summary>
        public int CheckCount
        {
            get { return checkCount; }
            set { checkCount = value; this.RaisePropertyChanged(() => CheckCount); }
        }

        private string printNum = "0";

        /// <summary>
        /// 自定义打印的数量
        /// </summary>
        public string PrintNum
        {
            get { return printNum; }
            set { printNum = value; this.RaisePropertyChanged(() => PrintNum); }
        }

        private ObservableCollection<SNEntity> SNsources;

        /// <summary>
        ///序列号实体集合
        /// </summary>
        public ObservableCollection<SNEntity> SNSources
        {
            get { return SNsources; }
            set { SNsources = value; this.RaisePropertyChanged(() => SNSources); }
        }

        private Visibility isVisibleLoading = Visibility.Collapsed;

        /// <summary>
        /// 是否显示加载动画
        /// </summary>
        public Visibility IsVisibleLoading
        {
            get { return isVisibleLoading; }
            set { isVisibleLoading = value; this.RaisePropertyChanged(() => IsVisibleLoading); }
        }

        private int printCopiesNum;

        /// <summary>
        /// 打印份数
        /// </summary>
        public int PrintCopiesNum
        {
            get { return printCopiesNum; }
            set { printCopiesNum = value; this.RaisePropertyChanged(() => PrintCopiesNum); }
        }

        #endregion 属性

        #region 命令

        private RelayCommand loadPageCmd;

        public RelayCommand LoadPageCmd
        {
            get
            {
                if (loadPageCmd == null)
                {
                    loadPageCmd = new RelayCommand(LoadPage);
                }
                return loadPageCmd;
            }
            set { loadPageCmd = value; }
        }

        private RelayCommand filterPNCmd;

        public RelayCommand FilterPNCmd
        {
            get
            {
                if (filterPNCmd == null)
                {
                    filterPNCmd = new RelayCommand(FilterPN);
                }
                return filterPNCmd;
            }
            set { filterPNCmd = value; }
        }

        private RelayCommand filterWOCmd;

        public RelayCommand FilterWOCmd
        {
            get
            {
                if (filterWOCmd == null)
                {
                    filterWOCmd = new RelayCommand(FilterWO);
                }
                return filterWOCmd;
            }
            set { filterWOCmd = value; }
        }

        private RelayCommand<string> comboPN_SelectionChangedCmd;

        public RelayCommand<string> ComboPN_SelectionChangedCmd
        {
            get
            {
                if (comboPN_SelectionChangedCmd == null)
                {
                    comboPN_SelectionChangedCmd = new RelayCommand<string>(ComboPN_SelectionChangedHandler);
                }
                return comboPN_SelectionChangedCmd;
            }
            set { comboPN_SelectionChangedCmd = value; }
        }

        private RelayCommand<string> comboWO_SelectionChangedCmd;

        public RelayCommand<string> ComboWO_SelectionChangedCmd
        {
            get
            {
                if (comboWO_SelectionChangedCmd == null)
                {
                    comboWO_SelectionChangedCmd = new RelayCommand<string>(ComboWO_SelectionChangedHandler);
                }
                return comboWO_SelectionChangedCmd;
            }
            set { comboWO_SelectionChangedCmd = value; }
        }

        private RelayCommand confirmPrintNumCmd;

        public RelayCommand ConfirmPrintNumCmd
        {
            get
            {
                if (confirmPrintNumCmd == null)
                {
                    confirmPrintNumCmd = new RelayCommand(ConfirmPrintNum);
                }
                return confirmPrintNumCmd;
            }
            set { confirmPrintNumCmd = value; }
        }

        private RelayCommand currentCheckedPosition;

        public RelayCommand CurrentCheckedPosition
        {
            get
            {
                if (currentCheckedPosition == null)
                {
                    currentCheckedPosition = new RelayCommand(() =>
                    {
                        MessageBox.Show("Test");
                    });
                }
                return currentCheckedPosition;
            }
            set { currentCheckedPosition = value; }
        }

        private RelayCommand printCmd;

        public RelayCommand PrintCmd
        {
            get
            {
                if (printCmd == null)
                {
                    printCmd = new RelayCommand(Print);
                }
                return printCmd;
            }
            set { printCmd = value; }
        }

        private RelayCommand reprintCmd;

        public RelayCommand ReprintCmd
        {
            get
            {
                if (reprintCmd == null)
                {
                    reprintCmd = new RelayCommand(Reprint);
                }
                return reprintCmd;
            }
            set { reprintCmd = value; }
        }

        private RelayCommand reprintListSelectedAllCmd;

        public RelayCommand ReprintListSelectedAllCmd
        {
            get
            {
                if (reprintListSelectedAllCmd == null)
                {
                    reprintListSelectedAllCmd = new RelayCommand(ReprintListSelectedAllHandler);
                }
                return reprintListSelectedAllCmd;
            }
            set { reprintListSelectedAllCmd = value; }
        }

        private RelayCommand reprintListUnSelectedAllCmd;

        public RelayCommand ReprintListUnSelectedAllCmd
        {
            get
            {
                if (reprintListUnSelectedAllCmd == null)
                {
                    reprintListUnSelectedAllCmd = new RelayCommand(ReprintListUnSelectedAllHandler);
                }
                return reprintListUnSelectedAllCmd;
            }
            set { reprintListUnSelectedAllCmd = value; }
        }

        private RelayCommand inputReprintCountCmd;

        public RelayCommand InputReprintCountCmd
        {
            get
            {
                if (inputReprintCountCmd == null)
                {
                    inputReprintCountCmd = new RelayCommand(InputReprintCount);
                }
                return inputReprintCountCmd;
            }
            set { inputReprintCountCmd = value; }
        }

        #endregion 命令

        #region 方法

        //页面加载
        private void LoadPage()
        {
            this.FillPNsToComboBox();
        }

        //输入补打的数量
        private void InputReprintCount()
        {
            ViewManager.Show("InputBox");
        }

        private void ReceiveReprintCount(string obj)
        {
            if (obj != "")
            {
                if (ReprintSns != null)
                {
                    var reprintCount = 0;
                    if (int.TryParse(obj, out reprintCount))
                    {
                        if (reprintCount > ReprintSns.Count)
                        {
                            MessageBox.Show(string.Format("输入补打的数量【{0}】大于待补打的总数量【{1}】，请重新输入。", reprintCount.ToString(), ReprintSns.Count.ToString()), "软件温馨提示!", MessageBoxButton.OK, MessageBoxImage.Error);
                        }
                        else
                        {
                            //循环设置已打印列表中选中状态

                            for (int i = 0; i < ReprintSns.Count; i++)
                            {
                                ReprintSns[i].IsChecked = false;
                            }
                            for (int i = 0; i < reprintCount; i++)
                            {
                                ReprintSns[i].IsChecked = true;
                            }
                        }
                    }
                    else
                    {
                        MessageBox.Show(string.Format("输入的内容【{0}】不是数字，请重新输入。", obj), "软件温馨提示!", MessageBoxButton.OK, MessageBoxImage.Error);
                    }
                }
            }
        }

        //补打列表上下文菜单取消事件处理
        private void ReprintListUnSelectedAllHandler()
        {
            if (ReprintSns != null)
            {
                var tmpReprintSns = ReprintSns;
                ReprintSns = new ObservableCollection<SNEntity>();
                foreach (var rs in tmpReprintSns)
                {
                    rs.IsChecked = false;
                    ReprintSns.Add(rs);
                }
            }
        }

        //补打列表上下文菜单全选事件处理
        private void ReprintListSelectedAllHandler()
        {
            if (ReprintSns != null)
            {
                var tmpReprintSns = ReprintSns;
                ReprintSns = new ObservableCollection<SNEntity>();
                foreach (var rs in tmpReprintSns)
                {
                    rs.IsChecked = true;
                    ReprintSns.Add(rs);
                }
            }
        }

        /// <summary>
        /// 打印标签
        /// </summary>
        private async void Print()
        {
            int printCopies = 1;//打印的份数
            TrackingEntity trackingEntity = null;
            string retMsg = string.Empty;//数据库返回的状态信息
            string startTime = string.Empty; //开始打印时间
            string stopTime = string.Empty; //结束打印时间
            string strTemplatePath = string.Empty; //模板路径
            DataTable dtPrintConfig = new DataTable();
            DataTable dtLastStatus = new DataTable();//序列号最后的状态信息
            ApplicationClass appClass = null;
            PartNumberEntity partNumberEntity = new PartNumberEntity();
            List<string> lstRecordSn = new List<string>();

            List<string> lstPreprintSns = new List<string>();//选择打印的序列号
            try
            {
                //判断机种是否为空，因为有的时候切换Tab选项卡的时候会情况下拉列表框中的内容，这是WPF潜在的Bug.
                if ((PN ?? "") == "")
                {
                    MessageBox.Show("请选择机种！", "软件温馨提示！", MessageBoxButton.OK, MessageBoxImage.Warning);
                    return;
                }
                //没有选中打印的序列号
                if (CheckCount <= 0)
                {
                    MessageBox.Show("请选择要打印的标签！", "软件温馨提示！", MessageBoxButton.OK, MessageBoxImage.Warning);
                    return;
                }
                //限制每次打印的数量《上限200》
                if (CheckCount > 200)
                {
                    MessageBox.Show("打印的数量单次不要超过200张！", "软件温馨提示！", MessageBoxButton.OK, MessageBoxImage.Warning);
                    return;
                }
                //关闭CodeSoft软件
                if (Process.GetProcessesByName("lppa").Length > 0)
                {
                    BusinessProcess.KillProcess("lppa");
                    //再次判断lppa进程是否存在
                    if (Process.GetProcessesByName("lppa").Length > 0)
                    {
                        MessageBox.Show("关闭【lppa】相关进行失败,请手动打开任务管理器关闭lppa前缀的进程.", "软件温馨提示!", MessageBoxButton.OK, MessageBoxImage.Warning);
                        return;
                    }
                }
                //获取机种的打印配置参数
                dtPrintConfig = BusinessProcess.GetLabelConfigByPartNumber(PN);
                if (dtPrintConfig.Rows.Count == 0)
                {
                    MessageBox.Show("没有找到机种【" + this.PN + "】打印配置参数,请检查是否配置打印参数！", "软件温馨提示！", MessageBoxButton.OK, MessageBoxImage.Warning);
                    return;
                }
                //拼接打印模版路径
                strTemplatePath = Path.Combine(Global.LabDirectory, dtPrintConfig.Rows[0]["TemplateName"].ToString());
                if (!File.Exists(strTemplatePath))
                {
                    MessageBox.Show("此路径下【" + strTemplatePath + "】没有找到打印模板,请检查打印模板是否存在！", "软件温馨提示！", MessageBoxButton.OK, MessageBoxImage.Warning);
                    return;
                }
                //打印的份数
                printCopies = Convert.ToInt32(dtPrintConfig.Rows[0]["PrintCopiesNum"].ToString() ?? "0");
                //选择的数量
                for (int i = 0; i < PreprintSns.Count; i++)
                {
                    if (PreprintSns[i].IsChecked)
                    {
                        //控制打印的份数
                        for (int j = 0; j < PrintCopiesNum; j++)
                        {
                            lstPreprintSns.Add(PreprintSns[i].SN);
                        }
                    }
                }
                appClass = new ApplicationClass();
                //打开模板
                appClass.Documents.Open(strTemplatePath, false);
                Document activeDocument = appClass.ActiveDocument;
                var variableName = string.Empty; //变量名
                var variableValue = string.Empty; //变量值

                //开始多线程操作
                await Task.Run(() =>
                {
                    //显示Loading加载动画
                    this.IsVisibleLoading = Visibility.Visible;
                    //每行打印几个标签
                    var columnsPerRow = Convert.ToInt32(dtPrintConfig.Rows[0]["ColumnsPerRow"].ToString() ?? "1");

                    //根据每行几列，计算每行的条码信息，
                    var perRowLabelInfos = DistributeLabels(lstPreprintSns, columnsPerRow);

                    foreach (var perRowLabelInfo in perRowLabelInfos)
                    {
                        startTime = System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                        for (int j = 0; j < dtPrintConfig.Rows.Count; j++)
                        {
                            var columnIndex = 0;
                            variableName = dtPrintConfig.Rows[j]["VariableName"].ToString();
                            variableValue = dtPrintConfig.Rows[j]["VariableValue"].ToString();
                            //机种
                            if (variableName.IndexOf("PN") > -1)
                            {
                                activeDocument.Variables.FormVariables.Item(variableName).Value = PN ?? "";
                            }
                            //针对于二维码(QR code)由序列号组成
                            else if (variableName.IndexOf("QRSN") > -1)
                            {
                                columnIndex = Convert.ToInt32(variableName.Replace("QRSN", "").Trim());
                                //添加内容
                                activeDocument.Variables.FormVariables.Item(variableName).Value = columnIndex > perRowLabelInfo.Count - 1 ? "" : perRowLabelInfo[columnIndex] ?? ""; //判断是不是有的行标签信息少于columnsPerRow变量值的，所以要做防呆，防止角标超上限
                            }
                            //序列号
                            else if (variableName.IndexOf("SN") > -1)
                            {
                                columnIndex = Convert.ToInt32(variableName.Replace("SN", "").Trim());
                                activeDocument.Variables.FormVariables.Item(variableName).Value = columnIndex > perRowLabelInfo.Count - 1 ? "" : perRowLabelInfo[columnIndex] ?? "";
                            }
                            else //其它情况直接用后台配置的参数添加变量的值
                            {
                                activeDocument.Variables.FormVariables.Item(variableName).Value = variableValue ?? "";
                            }
                        }
                        foreach (var tmpSn in perRowLabelInfo)
                        {
                            //记录打印的序列号《剔除重复项因为有的标签可能是一式两份》
                            if (!lstRecordSn.Contains(tmpSn))
                            {
                                lstRecordSn.Add(tmpSn);
                                //记录打印信息
                                LogHelper.WriteLabelLog(string.Format($"PRINT|{LogInInfo.User}|{System.DateTime.Now.ToString("yyyMMddHHmmss")}|{tmpSn}"));
                                //记录到后台
                                BusinessProcess.RecordPrintLog(tmpSn);
                            }
                        }
                        //打印标签
                        activeDocument.PrintDocument(1);
                    }
                    //批量录入打印标签Log信息
                    if (lstRecordSn.Count > 0)
                    {
                        StringBuilder strSns = new StringBuilder();
                        for (int i = 0; i < lstRecordSn.Count; i++)
                        {
                            //循环到最后一个不加分隔符防止传到后台处理的时候出现空序列号
                            if (i == lstRecordSn.Count - 1)
                            {
                                strSns.Append(lstRecordSn[i]);
                            }
                            else
                            {
                                strSns.Append(lstRecordSn[i] + "|");
                            }
                        }
                        trackingEntity = new TrackingEntity
                        {
                            Sn = strSns.ToString(),
                            Station = "LPRINT",
                            Result = "PASS",
                            EquipmentName = Environment.MachineName,
                            StartTime = startTime,
                            StopTime = System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                            Actor = LogInInfo.User
                        };
                        retMsg = BusinessProcess.AddBatchLabelPrintTracking(trackingEntity, out dtLastStatus);
                        string[] arrayMsg = new string[2];
                        arrayMsg = retMsg.Split('|');
                        if (arrayMsg[0] == "OK")
                        {
                            List<SNEntity> lstSnEntities = new List<SNEntity>();
                            for (int i = 0; i < lstRecordSn.Count; i++)
                            {
                                var sNEntities = PreprintSns.Where(x => x.SN == lstRecordSn[i]);
                                foreach (var s in sNEntities)
                                {
                                    lstSnEntities.Add(s);
                                }
                            }
                            //跨线程处理
                            DispatcherHelper.CheckBeginInvokeOnUI(() =>
                            {
                                foreach (var s in lstSnEntities)
                                {
                                    PreprintSns.Remove(s);
                                    PrintedSns.Add(new SNEntity { SN = s.SN, IsChecked = true });
                                }
                                //将后台传送过来的数据源显示再UI界面
                                SNSources = new ObservableCollection<SNEntity>();
                                for (int i = 0; i < dtLastStatus.Rows.Count; i++)
                                {
                                    SNSources.Add(new SNEntity
                                    {
                                        SN = dtLastStatus.Rows[i]["Sn"].ToString() ?? "",
                                        WO = dtLastStatus.Rows[i]["WO"].ToString() ?? "",
                                        PN = dtLastStatus.Rows[i]["PN"].ToString() ?? "",
                                        CompletedStation = dtLastStatus.Rows[i]["CompletedStation"].ToString() ?? "",
                                        PretestStation = dtLastStatus.Rows[i]["PretestStation"].ToString() ?? "",
                                        IsEnd = dtLastStatus.Rows[i]["IsEnd"].ToString() == "Y" ? "是" : "否",
                                        Actor = dtLastStatus.Rows[i]["Actor"].ToString(),
                                        CreateAt = dtLastStatus.Rows[i]["CreateAt"].ToString(),
                                        Year = dtLastStatus.Rows[i]["Year"].ToString()
                                    });
                                }
                                //显示选中的数量
                                this.CheckCount = PreprintSns.Count(x => x.IsChecked == true);
                            });
                        }
                    }
                    //关闭Loading加载动画
                    this.IsVisibleLoading = Visibility.Collapsed;
                });
            }
            catch (Exception ex)
            {
                this.IsVisibleLoading = Visibility.Collapsed;
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            finally
            {
                //释放关于codesoft的资源
                appClass?.Documents.CloseAll(false);
                appClass.EnableEvents = false;
                appClass?.Quit();
                appClass = null;
                GC.Collect();
            }
        }

        /// <summary>
        /// 补打
        /// </summary>
        private async void Reprint()
        {
            if ((PN ?? "") == "")
            {
                MessageBox.Show("机种信息不能为空", "软件温馨提示", MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }
            var preReprintSns = ReprintSns.Where(p => p.IsChecked == true).Select(s => s.SN).ToList();
            if (preReprintSns.Count() == 0 || preReprintSns.Count() > 200)
            {
                MessageBox.Show("没有选择补打的序列号或者选择的数量大于200", "软件温馨提示", MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }
            //检查Codesoft程序(lppa.exe)进程是否关闭，没有关闭先关闭
            var lppaProcess = Process.GetProcessesByName("lppa");
            //表示存在lppa进程
            if (lppaProcess.Length > 0)
            {
                if (!BusinessProcess.CloseProcessByCommandLine("lppa"))
                {
                    MessageBox.Show("关闭Codesoft软件失败,请手动在任务管理器进程里面关闭【lppa.exe】进程.", "软件温馨提示!", MessageBoxButton.OK, MessageBoxImage.Warning);
                    return;
                }
            }
            LabelManager2.ApplicationClass appClass = null;
            //异步执行打印
            await Task.Run(() =>
            {
                try
                {
                    IsVisibleLoading = Visibility.Visible;
                    //获取标签打印配置参数
                    var dtLabelConfig = BusinessProcess.GetLabelConfigByPartNumber(PN);
                    var templateName = dtLabelConfig.Rows[0]["TemplateName"].ToString();
                    var templatePath = Path.Combine(Global.LabDirectory, templateName);
                    //判断模版路径是否存在
                    if (!File.Exists(templatePath))
                    {
                        MessageBox.Show(string.Format("这个模版路径【{0}】不存在!", templatePath), "软件温馨提示!", MessageBoxButton.OK, MessageBoxImage.Warning);
                        return;
                    }
                    appClass = new LabelManager2.ApplicationClass();
                    appClass.Documents.Open(templatePath);
                    var activeDoc = appClass.ActiveDocument;
                    var templateVariables = dtLabelConfig.AsEnumerable().Select(dr => dr["VariableName"].ToString()).Distinct();

                    var variableName = string.Empty; //变量名
                    var variableValue = string.Empty; //变量值
                    //每行打印几个标签
                    var columnsPerRow = Convert.ToInt32(dtLabelConfig.Rows[0]["ColumnsPerRow"].ToString() ?? "1");

                    //根据每行几列，计算每行的条码信息，
                    var perRowLabelInfos = DistributeLabels(preReprintSns, columnsPerRow);

                    foreach (var perRowLabelInfo in perRowLabelInfos)
                    {
                        for (int j = 0; j < dtLabelConfig.Rows.Count; j++)
                        {
                            var columnIndex = 0;
                            variableName = dtLabelConfig.Rows[j]["VariableName"].ToString();
                            variableValue = dtLabelConfig.Rows[j]["VariableValue"].ToString();
                            //机种
                            if (variableName.IndexOf("PN") > -1)
                            {
                                activeDoc.Variables.FormVariables.Item(variableName).Value = PN ?? "";
                            }
                            //针对于二维码(QR code)由序列号组成
                            else if (variableName.IndexOf("QRSN") > -1)
                            {
                                columnIndex = Convert.ToInt32(variableName.Replace("QRSN", "").Trim());
                                //添加内容
                                activeDoc.Variables.FormVariables.Item(variableName).Value = columnIndex > perRowLabelInfo.Count - 1 ? "" : perRowLabelInfo[columnIndex] ?? ""; //判断是不是有的行标签信息少于columnsPerRow变量值的，所以要做防呆，防止角标超上限
                            }
                            //序列号
                            else if (variableName.IndexOf("SN") > -1)
                            {
                                columnIndex = Convert.ToInt32(variableName.Replace("SN", "").Trim());
                                activeDoc.Variables.FormVariables.Item(variableName).Value = columnIndex > perRowLabelInfo.Count - 1 ? "" : perRowLabelInfo[columnIndex] ?? "";
                            }
                            else //其它情况直接用后台配置的参数添加变量的值
                            {
                                activeDoc.Variables.FormVariables.Item(variableName).Value = variableValue ?? "";
                            }
                        }
                        //打印标签
                        activeDoc.PrintDocument(1);
                        foreach (var tmpSn in perRowLabelInfo)
                        {
                            //记录打印信息
                            LogHelper.WriteLabelLog(string.Format($"REPRINT|{LogInInfo.User}|{System.DateTime.Now.ToString("yyyMMddHHmmss")}|{tmpSn}"));
                            //记录到后台
                            BusinessProcess.RecordPrintLog(tmpSn, 1);
                        }
                    }
                }
                catch (Exception ex)
                {
                    LogHelper.WriteLog(ex.Message, ex);
                    throw new Exception(ex.Message);
                }
                finally
                {
                    IsVisibleLoading = Visibility.Collapsed;//隐藏加载提示
                    //释放关于codesoft的资源
                    appClass.Documents.CloseAll(false);
                    appClass.EnableEvents = false;
                    appClass.Quit();
                    appClass = null;
                }
            });
            //获取标签打印参数
        }

        /// <summary>
        /// 分发标签信息<根据条码总数和标签的每行打印列数，计算每行标签信息>
        /// </summary>
        /// <param name="barcodes">条码信息集合</param>
        /// <param name="columnsPerRow">标签每行的列数</param>
        /// <returns></returns>
        private static List<List<string>> DistributeLabels(List<string> barcodes, int columnsPerRow)
        {
            return barcodes.Select((barcode, index) => new { barcode, index }) // 为每个条码生成索引
                           .GroupBy(x => x.index / columnsPerRow) // 根据索引将条码分组，每组表示一行
                           .Select(group => group.Select(x => x.barcode).ToList()) // 为每个分组生成条码信息
                           .ToList(); // 转换为 List<List<string>>
        }

        /// <summary>
        /// 填充机种信息到下拉列表框中
        /// </summary>
        private void FillPNsToComboBox()
        {
            DataTable dtPNs = new DataTable();
            dtPNs = BusinessProcess.GetPNs(EnumPNType.All);
            PNs = new ObservableCollection<PartNumberEntity>();
            for (int i = 0; i < dtPNs.Rows.Count; i++)
            {
                PNs.Add(new PartNumberEntity
                {
                    PN = dtPNs.Rows[i]["PartNumber"].ToString()
                });
            }
        }

        /// <summary>
        /// 筛选机种下拉列表框中的数据
        /// </summary>
        private void FilterPN()
        {
            IsOpenComboPNDropDown = true;
            //当是第一次过滤的时候备份原始数据
            //这样是为了当不输入搜索条件时添加原始数据到列表中
            //当输入搜索条件时生成过滤集合绑定当下拉列表中
            if (isFirstFilterPN)
            {
                backupPNs = new ObservableCollection<PartNumberEntity>();
                backupPNs = PNs;
                isFirstFilterPN = false;
            }
            if (!string.IsNullOrEmpty(SearchPNText))
            {
                IEnumerable<PartNumberEntity> partNumberEntities = PNs.Where(s => s.PN.ToUpper().Contains(SearchPNText.ToUpper()));
                PNs = new ObservableCollection<PartNumberEntity>();
                foreach (var p in partNumberEntities)
                {
                    PNs.Add(p);
                }
            }
            else
            {
                PNs = backupPNs;
            }
        }

        /// <summary>
        /// 筛选工单下拉列表框中的数据
        /// </summary>
        private void FilterWO()
        {
            IsOpenComboWODropDown = true;
            //当是第一次过滤的时候备份原始数据
            //这样是为了当不输入搜索条件时添加原始数据到列表中
            //当输入搜索条件时生成过滤集合绑定当下拉列表中
            if (isFirstFilterWO)
            {
                backupWOs = new ObservableCollection<WOEntity>();
                backupWOs = WOs;
                isFirstFilterWO = false;
            }
            if (!string.IsNullOrEmpty(SearchWOText) && WOs != null)
            {
                IEnumerable<WOEntity> WOEntities = WOs.Where(s => s.WO.ToUpper().Contains(SearchWOText.ToUpper()));
                WOs = new ObservableCollection<WOEntity>();
                foreach (var w in WOEntities)
                {
                    WOs.Add(w);
                }
            }
            else
            {
                WOs = backupWOs;
            }
        }

        /// <summary>
        /// 机种下拉框选项改变事件处理函数
        /// </summary>
        private void ComboPN_SelectionChangedHandler(string param)
        {
            if (param == null)
            {
                return;
            }
            DataTable dtWOs = new DataTable();
            DataTable dtPNInfo = new DataTable();
            dtWOs = BusinessProcess.GetWOsByPN(param);
            WOs = new ObservableCollection<WOEntity>();
            for (int i = 0; i < dtWOs.Rows.Count; i++)
            {
                WOs.Add(new WOEntity { WO = dtWOs.Rows[i]["WO"].ToString() });
            }
            dtPNInfo = BusinessProcess.GetPNInfo(param);
            this.PrintCopiesNum = Convert.ToInt32(dtPNInfo.Rows[0]["PrintCopiesNum"] == DBNull.Value ? "0" : dtPNInfo.Rows[0]["PrintCopiesNum"].ToString() ?? "0");
        }

        private void ComboWO_SelectionChangedHandler(string param)
        {
            string printStatus = string.Empty;//打印的状态
            DataTable dtPrintInfo = new DataTable();
            dtPrintInfo = BusinessProcess.GetLabelPrintInfoByWO(param);
            PreprintSns = new ObservableCollection<SNEntity>();
            PrintedSns = new ObservableCollection<SNEntity>();
            ReprintSns = new ObservableCollection<SNEntity>();
            SNSources = new ObservableCollection<SNEntity>();
            for (int i = 0; i < dtPrintInfo.Rows.Count; i++)
            {
                printStatus = dtPrintInfo.Rows[i]["IsPrinted"].ToString();
                if (printStatus == "N")
                {
                    //填充预打印列表
                    PreprintSns.Add(new SNEntity { SN = dtPrintInfo.Rows[i]["Sn"].ToString(), IsChecked = false });
                }
                else
                {
                    //填充打印列表
                    PrintedSns.Add(new SNEntity { SN = dtPrintInfo.Rows[i]["Sn"].ToString(), IsChecked = true });
                    //填充补打列表
                    ReprintSns.Add(new SNEntity { SN = dtPrintInfo.Rows[i]["Sn"].ToString(), IsChecked = false });
                }
                SNSources.Add(new SNEntity
                {
                    SN = dtPrintInfo.Rows[i]["Sn"].ToString(),
                    WO = dtPrintInfo.Rows[i]["WO"].ToString(),
                    PN = dtPrintInfo.Rows[i]["PN"].ToString(),
                    CompletedStation = dtPrintInfo.Rows[i]["CompletedStation"].ToString(),
                    PretestStation = dtPrintInfo.Rows[i]["PretestStation"].ToString(),
                    IsEnd = dtPrintInfo.Rows[i]["IsEnd"].ToString(),
                    Actor = dtPrintInfo.Rows[i]["Actor"].ToString(),
                    CreateAt = dtPrintInfo.Rows[i]["CreateAt"].ToString(),
                    Year = dtPrintInfo.Rows[i]["Year"].ToString()
                });
            }
            NoPrintCount = PreprintSns.Count;
        }

        private void ConfirmPrintNum()
        {
            int number = 0;
            if (BusinessProcess.IsNumber(this.PrintNum))
            {
                int.TryParse(PrintNum, out number);
                if (number <= NoPrintCount)
                {
                    for (int i = 0; i < PreprintSns.Count; i++)
                    {
                        PreprintSns[i].IsChecked = false;
                    }
                    for (int i = 0; i < number; i++)
                    {
                        PreprintSns[i].IsChecked = true;
                    }
                    this.CheckCount = number;
                }
                else
                {
                    MessageBox.Show("输入的数量【" + PrintNum + "】大于总数量【" + NoPrintCount.ToString() + "】", "软件温馨提示", MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
            else
            {
                MessageBox.Show("输入的不是大于零的数字", "软件温馨提示!", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        /// <summary>
        /// 预打印列表复选框点击事件
        /// </summary>
        /// <param name="param"></param>
        private void LstPreprintSnCheckBoxClickHandler(string param)
        {
            this.CheckCount = PreprintSns.Count(x => x.IsChecked == true);
        }

        #endregion 方法
    }
}